"""
HTTP客户端工具
支持代理配置的统一HTTP请求封装
"""
from typing import Dict, Any, Optional
import time
import random
import requests
from loguru import logger


class HTTPClient:
    """HTTP客户端，支持代理配置"""
    
    def __init__(self, config: Optional[Dict[str, Any]] = None):
        """
        初始化HTTP客户端
        
        Args:
            config: 配置字典，可包含：
                - proxy: 代理配置 {"http": "http://proxy:port", "https": "https://proxy:port"}
                - proxies: 同上，备用字段名
                - timeout: 超时时间
                - verify: SSL验证（默认True）
        """
        self.config = config or {}
        self.proxy = self.config.get("proxy") or self.config.get("proxies")
        self.timeout = self.config.get("timeout", 60)
        self.verify = self.config.get("verify", True)
        self.max_retries = int(self.config.get("maxRetries", 0))
        
        # 构建requests session
        self.session = requests.Session()
        
        # 设置代理
        if self.proxy:
            self.session.proxies.update(self.proxy)
            logger.debug(f"HTTP客户端已配置代理: {self.proxy}")
        
        # 设置SSL验证
        self.session.verify = self.verify
    
    def _sleep_backoff(self, attempt: int):
        """指数退避 + 抖动"""
        base = 1.5 ** max(0, attempt - 1)
        sleep_seconds = min(8.0, base) + random.uniform(0, 0.3)
        time.sleep(sleep_seconds)
    
    def post(self, url: str, headers: Optional[Dict[str, str]] = None, 
             json_data: Optional[Dict[str, Any]] = None, 
             data: Optional[Dict[str, Any]] = None,
             timeout: Optional[Any] = None) -> requests.Response:
        """
        发送POST请求
        
        Args:
            url: 请求URL
            headers: 请求头
            json_data: JSON数据
            data: 表单数据
            timeout: 超时时间（秒），None使用默认值
            
        Returns:
            Response对象
        """
        effective_timeout = timeout or self.timeout
        
        attempts = self.max_retries + 1
        last_exc: Optional[Exception] = None
        for attempt in range(1, attempts + 1):
            try:
                response = self.session.post(
                    url,
                    headers=headers,
                    json=json_data,
                    data=data,
                    timeout=effective_timeout
                )
                return response
            except requests.exceptions.ProxyError as e:
                logger.error(f"代理错误: {e}")
                raise
            except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
                last_exc = e
                logger.error(f"请求超时/连接错误（第 {attempt}/{attempts} 次）: {e}")
                if attempt < attempts:
                    self._sleep_backoff(attempt)
                    continue
                raise
            except Exception as e:
                last_exc = e
                logger.error(f"HTTP请求失败（第 {attempt}/{attempts} 次）: {e}")
                if attempt < attempts:
                    self._sleep_backoff(attempt)
                    continue
                raise
    
    def get(self, url: str, headers: Optional[Dict[str, str]] = None,
            params: Optional[Dict[str, Any]] = None,
            timeout: Optional[Any] = None) -> requests.Response:
        """
        发送GET请求
        
        Args:
            url: 请求URL
            headers: 请求头
            params: URL参数
            timeout: 超时时间（秒），None使用默认值
            
        Returns:
            Response对象
        """
        effective_timeout = timeout or self.timeout
        
        attempts = self.max_retries + 1
        last_exc: Optional[Exception] = None
        for attempt in range(1, attempts + 1):
            try:
                response = self.session.get(
                    url,
                    headers=headers,
                    params=params,
                    timeout=effective_timeout
                )
                return response
            except requests.exceptions.ProxyError as e:
                logger.error(f"代理错误: {e}")
                raise
            except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
                last_exc = e
                logger.error(f"请求超时/连接错误（第 {attempt}/{attempts} 次）: {e}")
                if attempt < attempts:
                    self._sleep_backoff(attempt)
                    continue
                raise
            except Exception as e:
                last_exc = e
                logger.error(f"HTTP请求失败（第 {attempt}/{attempts} 次）: {e}")
                if attempt < attempts:
                    self._sleep_backoff(attempt)
                    continue
                raise
    
    def close(self):
        """关闭session"""
        self.session.close()

